package Subkiller;

import java.awt.*;        
import java.awt.event.*;
import javax.swing.*;


/**
 * This panel implements a simple arcade game in which the user tries to blow
 * up a "submarine" (a black oval) by dropping "depth charges" (a red disk) from 
 * a "boat" (a blue roundrect).  The user moves the boat with the left- and 
 * right-arrow keys and drops the depth charge with the down-arrow key.
 * The sub moves left and right erratically along the bottom of the panel.
 * This class contains a main() routine to allow it to be run as a program.
 */
public class SubKiller extends JPanel {
   
   public static void main(String[] args) {
      JFrame window = new JFrame("Sub Killer Game");
      SubKiller content = new SubKiller();
      window.setContentPane(content);
      window.setSize(600, 480);
      window.setLocation(100,100);
      window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      window.setResizable(false);  // User can't change the window's size.
      window.setVisible(true);
   }
   
   //------------------------------------------------------------------------

   private Timer timer;        // Timer that drives the animation.

   private int width, height;  // The size of the panel -- the values are set
                               //    the first time the paintComponent() method
                               //    is called.  This class is not designed to
                               //    handle changes in size; once the width and
                               //    height have been set, they are not changed.
                               //    Note that width and height cannot be set
                               //    in the constructor because the width and
                               //    height of the panel have not been set at
                               //    the time that the constructor is called.

   private Boat boat;          // The boat, bomb, and sub objects are defined
   private Bomb bomb;          //    by nested classes Boat, Bomb, and Submarine,
   private Submarine sub;      //    which are defined later in this class.
                               //    Note that the objects are created in the
                               //    paintComponent() method, after the width
                               //    and height of the panel are known.


   /**
    * The constructor sets the background color of the panel, creates the
    * timer, and adds a KeyListener, FocusListener, and MouseListener to the
    * panel.  These listeners, as well as the ActionListener for the timer
    * are defined by anonymous inner classes.  The timer will run only
    * when the panel has the input focus.
    */
   public SubKiller() {
   
      setBackground( new Color(0,200,0) ); 
   
      ActionListener action = 
         new ActionListener() {
            // Defines the action taken each time the timer fires.
            public void actionPerformed(ActionEvent evt) {
               if (boat != null) {
                  boat.updateForNewFrame();
                  bomb.updateForNewFrame();
                  sub.updateForNewFrame();
                  sub.currentBoat=boat;
               }
               repaint();
            }
         };
      timer = new Timer( 30, action );  // Fires every 30 milliseconds.
   
      addMouseListener( 
         new MouseAdapter() {
            // The mouse listener simply requests focus when the user
            // clicks the panel.
            public void mousePressed(MouseEvent evt) {
               requestFocus();
            }
         } );
   
      addFocusListener( 
         new FocusListener() {
            // The focus listener starts the timer when the panel gains
            // the input focus and stops the timer when the panel loses
            // the focus.  It also calls repaint() when these events occur.
            public void focusGained(FocusEvent evt) {
               timer.start();
               repaint();
            }
            public void focusLost(FocusEvent evt) {
               timer.stop();
               repaint();
            }
         } );
   
      addKeyListener( 
         new KeyAdapter() {
            // The key listener responds to keyPressed events on the panel. Only
            // the left-, right-, and down-arrow keys have any effect.  The left- and
            // right-arrow keys move the boat while down-arrow releases the bomb.
            public void keyPressed(KeyEvent evt) {
               int code = evt.getKeyCode();  // Which key was pressed?
               if (code == KeyEvent.VK_LEFT) {
                  // Move the boat left.  (If this moves the boat out of the frame, its
                  // position will be adjusted in the boat.updateForNewFrame() method.)
                  boat.centerX -= 15;
               }
               else if (code == KeyEvent.VK_RIGHT) {  
                  // Move the boat right.  (If this moves boat out of the frame, its
                  // position will be adjusted in the boat.updateForNewFrame() method.)
                  boat.centerX += 15;
               }
               else if (code == KeyEvent.VK_DOWN) {
                  // Start the bomb falling, if it is not already falling.
                  if ( bomb.isFalling == false )
                     bomb.isFalling = true;
               }
            }
         } );
   
   } // end constructor


   /**
    * The paintComponent() method draws the current state of the game.  It
    * draws a gray or cyan border around the panel to indicate whether or not
    * the panel has the input focus.  It draws the boat, sub, and bomb by
    * calling their respective draw() methods.
    */
   public void paintComponent(Graphics g) {
   
      super.paintComponent(g);  // Fill panel with background color, green.
      
      Graphics2D g2 = (Graphics2D)g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
   
      if (boat == null) {
             // The first time that paintComponent is called, it assigns
             // values to the instance variables.
         width = getWidth();
         height = getHeight();
         boat = new Boat();
         sub = new Submarine();
         bomb = new Bomb();
      }
   
      if (hasFocus())
         g.setColor(Color.CYAN);
      else {
         g.setColor(Color.BLACK);
         g.drawString("CLICK TO ACTIVATE", 20, 30);
         g.setColor(Color.GRAY);
      }
      g.drawRect(0,0,width-1,height-1);  // Draw a 3-pixel border.
      g.drawRect(1,1,width-3,height-3);
      g.drawRect(2,2,width-5,height-5);
   
      boat.draw(g);
      sub.draw(g);
      bomb.draw(g);
   
   } // end paintComponent()


   /**
    * This nested class defines the boat.  Note that its constructor cannot
    * be called until the width of the panel is known!
    */
   private class Boat {
      int centerX, centerY;  // Current position of the center of the boat.
      public int score;
      Boat() { // Constructor centers the boat horizontally, 80 pixels from top.
         score = 0;
         centerX = width/2;
         centerY = 80;
         
      }
      void updateForNewFrame() { // Makes sure boat has not moved off screen.
         if (centerX < 0)
            centerX = 0;
         else if (centerX > width)
            centerX = width;
      }
      void draw(Graphics g) {  // Draws the boat at its current location.
         g.setColor(Color.BLACK);
         g.drawString("Your Score is="+score,400,30);
         g.setColor(Color.BLUE);
         g.fillRoundRect(centerX - 40, centerY - 20, 80, 40, 20, 20);
      }
   } // end nested class Boat


   /**
    * This nested class defines the bomb. 
    */
   private class Bomb {
      int centerX, centerY; // Current position of the center of the bomb.
      boolean isFalling;    // If true, the bomb is falling; if false, it
                           // is attached to the boat.
      Bomb() { // Constructor creates a bomb that is initially attached to boat.
         isFalling = false;
      }
      void updateForNewFrame() {  // If bomb is falling, take appropriate action.
         if (isFalling) {
            if (centerY > height) {
                   // Bomb has missed the submarine.  It is returned to its
                   // initial state, with isFalling equal to false.
               isFalling = false;
            }
            else if (Math.abs(centerX - sub.centerX) <= 36 &&
                   Math.abs(centerY - sub.centerY) <= 21) {
                   // Bomb has hit the submarine.  The submarine
                   // enters the "isExploding" state.
               sub.isExploding = true;
               sub.explosionFrameNumber = 1;
               isFalling = false;  // Bomb reappears on the boat.
            }
            else {
                   // If the bomb has not fallen off the panel or hit the
                   // sub, then it is moved down 10 pixels.
               centerY += 10;
            }
         }
      }
      void draw(Graphics g) { // Draw the bomb.
         if ( ! isFalling ) {  // If not falling, set centerX and centerY
                              // to show the bomb on the bottom of the boat.
            centerX = boat.centerX;
            centerY = boat.centerY + 23;
         }
         g.setColor(Color.RED);
         g.fillOval(centerX - 8, centerY - 8, 16, 16);
      }
   } // end nested class Bomb


   /**
    * This nested class defines the sub.  Note that its constructor cannot
    * be called until the width of the panel is known!
    */
   private class Submarine {
      int centerX, centerY; // Current position of the center of the sub.
      boolean isMovingLeft; // Tells whether the sub is moving left or right
      boolean isExploding;  // Set to true when the sub is hit by the bomb.
      int explosionFrameNumber;  // If the sub is exploding, this is the number
      public Boat currentBoat;
                               //   of frames since the explosion started.
      Submarine() {  // Create the sub at a random location 40 pixels from bottom.
         centerX = (int)(width*Math.random());
         centerY = height - 40;
         isExploding = false;
         isMovingLeft = (Math.random() < 0.5);
      }
      void updateForNewFrame() { // Move sub or increase explosionFrameNumber.
         if (isExploding) {
                // If the sub is exploding, add 1 to explosionFrameNumber.
                // When the number reaches 15, the explosion ends and the
                // sub reappears in a random position.
            explosionFrameNumber++;
            currentBoat = boat;
            if (explosionFrameNumber == 15) { 
               centerX = (int)(width*Math.random());
               centerY = height - 40;
               isExploding = false;
               isMovingLeft = (Math.random() < 0.5);
            }
         }
         else { // Move the sub.
            if (Math.random() < 0.04) {  
                   // In one frame out of every 25, on average, the sub
                   // reverses its direction of motion.
               isMovingLeft = ! isMovingLeft; 
            }
            if (isMovingLeft) { 
                   // Move the sub 5 pixels to the left.  If it moves off
                   // the left edge of the panel, move it back to the left
                   // edge and start it moving to the right.
               centerX -= 5;  
               if (centerX <= 0) {  
                  centerX = 0; 
                  isMovingLeft = false; 
               }
            }
            else {
                   // Move the sub 5 pixels to the right.  If it moves off
                   // the right edge of the panel, move it back to the right
                   // edge and start it moving to the left.
               centerX += 5;         
               if (centerX > width) {  
                  centerX = width;   
                  isMovingLeft = true; 
               }
            }
         }
      }
      void draw(Graphics g) {  // Draw sub and, if it is exploding, the explosion.
         g.setColor(Color.BLACK);
         g.fillOval(centerX - 30, centerY - 15, 60, 30);
         
         
         if (isExploding) {
                // Draw an "explosion" that grows in size as the number of
                // frames since the start of the explosion increases.
            g.setColor(Color.YELLOW);
            g.fillOval(centerX - 4*explosionFrameNumber,
                   centerY - 2*explosionFrameNumber,
                   8*explosionFrameNumber,
                   4*explosionFrameNumber);
            g.setColor(Color.RED);
            g.fillOval(centerX - 2*explosionFrameNumber,
                   centerY - explosionFrameNumber/2,
                   4*explosionFrameNumber,
                   explosionFrameNumber);
                   
            currentBoat.score+=10;
            System.out.println("current score is ="+explosionFrameNumber);
            
           
         }
      }
   } // end nested class Submarine    


} // end class SubKiller
